#ifndef _MUNIX_TYPES_H_
#define _MUNIX_TYPES_H_
/*******************************************************************************
 ** Name: types.h                                                             **
 ** Description:              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the license.txt within              **
 ** this distribution or at http://www.munixos.net/licensing.                 **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $HOME/license.txt.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 **                                                                           **
 ** Copyright (c) 2009-2010  Barry Gian James.                                **
 ** All rights reserved.                                                      **
 **                                                                           **
 ** Ref: $HeadURL$
 ******************************************************************************/
// Portions (C) 2011 OpenHouseware, LLC.
// All Rights Reserved

// $Id$
// Last Modified $Date$ by $Author: bjames $

#ifdef __cplusplus
extern "C" {
#endif

class Integer24;

// AVR-related extensions
#ifdef __AVR__
#if !defined(uint8_t)
typedef unsigned char	uint8_t;
#endif
#if !defined(uint16_t)
typedef unsigned int	uint16_t;
#endif
#if !defined(uint24_t)
typedef Integer24		uint24_t;
#endif
#if !defined(uint32_t)
typedef unsigned long	uint32_t;
#endif
#if !defined(uint64_t)
typedef unsigned long long int uint64_t;
#endif
#if !defined (int8_t)
typedef signed char		int8_t;
#endif
#ifndef int16_t
typedef int				int16_t;
#endif
#if !defined(int32_t)
typedef long			int32_t;
#endif
#if !defined(int64_t)
typedef long long int	int64_t;
#endif
#if !defined(byte)
typedef unsigned char	byte;
#endif
#if !defined(word)
typedef unsigned short	word;
#endif
#if !defined(memaddr_t)
typedef Integer24		memaddr_t;
#endif
#if !defined(uintmax_t)
typedef uint64_t		uintmax_t;
#endif
#if !defined(intmax_t)
typedef int64_t			intmax_t;
#endif

// POSIX Extensions
typedef unsigned char	uchar_t;
typedef unsigned short	ushort_t;
typedef unsigned int	uint_t;
typedef unsigned long	ulong_t;
typedef char *			caddr_t;
typedef long			daddr_t;

// Typedefs for shorthand
//typedef uint8_t		uint8;
//typedef uint16_t	uint16;
//typedef uint32_t	uint32;
//typedef unsigned char uchar;
#if !defined(time_t)
typedef unsigned long   time_t;
#endif
#if !defined(register_t)
typedef unsigned char		register_t;
#endif
#if !defined (register16_t)
typedef uint16_t	register16_t;
#endif

#if !defined(pid_t)
typedef uint8_t		pid_t;
#endif
#if !defined(uid_t)
typedef uint8_t		uid_t;
#endif
#if !defined(guid_t)
typedef uint8_t		guid_t;
#endif

#endif	/* __AVR__ */

// This type object can be used anywhere you want to use a 24-bit
// unsigned integer, but is especially useful with flash and sram
// memories that use <= 24 bits for addresses.
class Integer24
{
public:
	Integer24() {a[0] = a[1] = a[2] = 0; }
	Integer24(const uint32_t i) {
		a[0] = (i);
		a[1] = (i >> 8);
		a[2] = (i >> 16);
	}

	// operator overloading
	Integer24 &		operator = (const Integer24 & i) {
		a[0] = i[0];
		a[1] = i[1];
		a[2] = i[2];
		return * this;
	}
	Integer24 &		operator += (const Integer24 & i) {
		a[0] += i[0];
		a[1] += i[1];
		a[2] += i[2];
		return * this;
	}
	Integer24 &		operator -= (const Integer24 & i) {
		a[0] -= i[0];
		a[1] -= i[1];
		a[2] -= i[2];
		return * this;
	}
	const Integer24 operator + (const Integer24& i) const {
		Integer24 result(A() + i.A());
		return result;
	}
	const Integer24 operator - (const Integer24& i) const {
		Integer24 result(A() - i.A());
		return result;
	}
	const Integer24 operator * (const Integer24 & i) const {
		Integer24 result(A() * i.A());
		return result;
	}
	const Integer24 operator / (const Integer24 & i) const {
		Integer24 result((int32_t)(A() / i.A()));
		return result;
	}
	bool	operator < (const Integer24 & i) const { return A() < i.A(); }
	bool	operator <= (const Integer24 & i) const { return A() <= i.A(); }
	bool	operator > (const Integer24 & i ) const { return A() > i.A(); }
	bool	operator >= (const Integer24 & i) const { return A() >= i.A(); }
	bool	operator == (const Integer24 & i) const { return A() == i.A(); }
	bool	operator != (const Integer24 & i) const { return A() != i.A(); }

	uint8_t	operator [] (const uint8_t i) {
		if (i < 0 || i > 2) return 0;
		return a[i];
	}
	const uint8_t operator [] (const uint8_t i) const {
		if (i < 0 || i > 2) return 0;
		return a[i];
	}

	operator uint32_t () const { return A(); }

	// bitwise operators
	uint32_t	operator & (const Integer24 & i) { return A() & i.A(); }
	uint32_t	operator & (const uint32_t m) { return A() & m; }
	uint32_t	operator | (const Integer24 & i) { return A() | i.A(); }
	uint32_t	operator | (const uint32_t m) { return A() | m; }
	uint32_t	operator ~ () { return ~A(); }
	// JIRA STDCPP-#
	Integer24 &	operator &= (const Integer24 & i) {
		Integer24 i24 = *this & i;
		*this = i24;
		return *this;
	}
	Integer24 &	operator |= (const Integer24 & i) {
		Integer24 i24 = *this | i;
		*this = i24;
		return *this;
	}
//	Integer24 & operator ~= () {
//		Integer24 i24 = ~(*this);
//
//	}

protected:
	const uint32_t A() const {
		uint32_t result = (
			  (uint32_t)(a[2]*0x10000)
			| (uint32_t)(a[1] * 0x100)
			| (uint32_t)(a[0])
		);
		return result;
	}

private:
	uint8_t	a[3];
};



#ifdef __cplusplus
}
#endif

#endif /* TYPES_H_ */
